Function.prototype.myCall = function(context) {
    if (typeof this !== 'function') {
        throw TypeError('caller must be a function')
    }
    context = context || window
    context.fn = this
    const args = [...arguments].slice(1)
    let res = context.fn(...args)
    delete context.fn
    return res
}

Function.prototype.myApply = function (context) {
    if (typeof this !== 'function') {
        throw TypeError('caller must be a function')
    }
    context = context || window
    const fnSym = Symbol()
    context[fnSym] = this
    let res = null
    if (arguments[1]) {
        res = context[fnSym](...arguments[1])
    } else {
        res = context[fnSym]()
    }
    delete context[fnSym]
    return res
}

Function.prototype.myBind = function(context) {
    if (typeof this !== 'function') {
        throw TypeError('caller must be a function')
    }
    context = context || window
    let fn = this
    let args = [...arguments].slice(1)
    return function Fn() {
        fn.apply(
            this instanceof Fn ? this : context,
            args.concat(...arguments)
        )
    }
}